﻿

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using DataLoadingModule.ViewModel;
using SharedResources.Model;
using SharedResources.Utilities;
using SharedResources.ViewModel;
using VisualisationModule.Model;

namespace VisualisationModule.ViewModel
{
    public class VisualisationAreaViewModel : BaseViewModel
    {

        public VisualisationAreaViewModel()
        {
            UnderlyingData.OnDatasetAdded += new EventHandler(UpdateVisualisationWhenDataAdded);
        }

        private void UpdateVisualisationWhenDataAdded(object sender, EventArgs e)
        {
            var datasetAddedArgs = e as DatasetAddedEventArgs;
            if(datasetAddedArgs != null)
            {
                _currentMessageStatus = CenterMessageStatus.DataLoadedNotSmoothed;
                _centerMessageOptions = null;
                VisualisationHeight = datasetAddedArgs.MaxBounds.Y - datasetAddedArgs.MinBounds.Y;
                VisualisationWidth = datasetAddedArgs.MaxBounds.X - datasetAddedArgs.MinBounds.X;
                OnPropertyChanged("VisualisationHeight");
                OnPropertyChanged("VisualisationWidth");
                OnPropertyChanged("CenterMessageOptions");
            }
        }

        #region CenterMessage

        private Visibility _centerMessageVisibility = Visibility.Visible;
        public Visibility CenterMessageVisibility
        {
            get { return _centerMessageVisibility; }
        }

        public void ToggleCenterMessageVisibility()
        {
            switch (_centerMessageVisibility)
            {
                case Visibility.Visible:
                    _centerMessageVisibility = Visibility.Hidden;
                    break;
                case Visibility.Hidden:
                    _centerMessageVisibility = Visibility.Visible;
                    break;
            }
        }

        private string _centerMessage = "There is no dataset to visualise.";
        public string CenterMessage
        {
            get { return _centerMessage; }
            set
            {
                _centerMessage = value;
                OnPropertyChanged("CenterMessage");
            }
        }

        private CenterMessageOptions _centerMessageOptions;
        public List<ListViewItem> CenterMessageOptions
        {
            get
            {
                if(_centerMessageOptions == null)
                {
                    _centerMessageOptions = new CenterMessageOptions();
                    GenerateMessageOptions(_currentMessageStatus);
                }
                return _centerMessageOptions.Options;
            }
        }

        private void GenerateMessageOptions(CenterMessageStatus status)
        {
            //this method is called to make the message options
            switch(status)
            {
                case CenterMessageStatus.Initial:
                    _centerMessageOptions.AddOption("Load a dataset file.", () => new DatasetWizardViewModel().ShowWizard()); //show the wizard
                    _centerMessageOptions.AddOption("Load a saved file.", ()=>{}); //to be implemented
                    break;

                case CenterMessageStatus.DataLoadedNotSmoothed:
                    CenterMessage = "Your options:";
                    _centerMessageOptions.AddOption("View all trajectories at all times (unsmoothed)", ()=>
                                                                                                           {
                                                                                                               VisualiseAllDatasets();
                                                                                                               _centerMessageVisibility = Visibility.Hidden;
                                                                                                               OnPropertyChanged("CenterMessageVisibility");
                                                                                                           });
                    _centerMessageOptions.AddOption("Smooth data (allows more visualisation options)", () =>
                                                                                                           {
                                                                                                               new SmoothDatasetViewModel().ShowSmoothDataSetPopUp();
                                                                                                           });
                    break;

                case CenterMessageStatus.DataSmoothed:
                    CenterMessage = "Your options:";
                    _centerMessageOptions.AddOption("All Trajectories at all times (unsmoothed)", ()=>{});
                    break;

                default:
                    throw new ArgumentOutOfRangeException("status");
            }
        }

        //Need states because the center message can change depending on user interactions

        private CenterMessageStatus _currentMessageStatus = CenterMessageStatus.Initial;
        //on startup set it to intial
        

        public enum CenterMessageStatus
        {//autoincrementing enum
            Initial = 1,
            DataLoadedNotSmoothed,
            DataSmoothed
        }
        #endregion

        //http://stackoverflow.com/questions/1150060/how-to-draw-line-of-ten-thousands-of-points-with-wpf-within-0-5-second

        private ObservableCollection<VisualisedTrajectory> _trajectories = new ObservableCollection<VisualisedTrajectory>();
        public ObservableCollection<VisualisedTrajectory> Trajectories
        {
            get { return _trajectories; } 
        }

        #region VisualisationDimensions

        private double _visualisationWidth = 100;
        public double VisualisationWidth
        {
            get { return _visualisationWidth; }
            private set { _visualisationWidth = value; }
        }

        private double _visualisationHeight = 100;
        public double VisualisationHeight
        {
            get { return _visualisationHeight; }
            private set { _visualisationHeight = value; }
        }

        #endregion

        public void VisualiseAllDatasets()
        {
            foreach (var selectableDataset in UnderlyingData.SelectableData)
            {
                if(selectableDataset.Item2.WillVisualise)
                {
                    foreach (var pathPoints in selectableDataset.Item2.GetVisualisationPoints())
                    {
                        Trajectories.Add(new VisualisedTrajectory(CreatePathData(pathPoints)));
                    }
                }
            }
        }

        private Geometry CreatePathData(IList<Point> points)
        {
            var geometry = new StreamGeometry {FillRule = FillRule.EvenOdd};
            using (StreamGeometryContext ctx = geometry.Open())
            {
                ctx.BeginFigure(points[0], false, false); //use the first index
                ctx.PolyLineTo(points, true, true);
            }
            return (Geometry)geometry.GetAsFrozen(); 
        }

    }
}
